#ifndef _I_LOGGER_H
#define _I_LOGGER_H
#include <string>
#include "IPlugin.h"

class LoggerAppendData {
public:
    std::string fileName;
    int line = 0;
    std::string funcName;
};

class ILoggerAppendData : public IPlugin{
public:
    virtual std::string toString(const LoggerAppendData &data) = 0;
};
enum LogLevelType {
    LOG_DEFAULT =             -1,   /**< Default log level */
    LOG_OFF     =           0x00,   /**< Log level off */
    LOG_FATAL   =           0x01,   /**< fatal system error */
    LOG_ERROR   =           0x02,   /**< error with impact to correct functionality */
    LOG_WARN    =           0x03,   /**< warning, correct behaviour could not be ensured */
    LOG_INFO    =           0x04,   /**< informational */
    LOG_DEBUG   =           0x05,   /**< debug  */
    LOG_VERBOSE =           0x06,   /**< highest grade of information */
    LOG_MAX                         /**< maximum value, used for range check */

};

class ILoggerSink : public IPlugin{
public:
    virtual ~ILoggerSink() = default;
    virtual void printLine(int level, const char *) = 0;
};
/**
 * @brief 
 * <bean name="log" interface="ILogger" implemation="SimpleLogger">
 *  <log level="6"/>
 *  <sink implemation="LoggerConsoleSink"/>
 *  <append implemation="SimpleLoggerAppendData" filter="all"/>
 * </bean>
 */
class ILogger : public IPlugin{
public:
    virtual void logger(LoggerAppendData *data,LogLevelType nLogLevel,const char* pFormat, ...);
    virtual void log(LoggerAppendData *data,LogLevelType nLogLevel, const std::string &content) = 0;
};

#define LOG(LOGLEVEL, FORMAT, ARGS...) \
    do {LoggerAppendData __data__; \
    __data__.fileName = __FILE__;\
    __data__.funcName = __FUNCTION__;\
    __data__.line = __LINE__;\
    ILogger *bean = Bean<ILogger>("logger").pointer();\
    if (bean)bean->logger(&__data__, LOGLEVEL, FORMAT, ##ARGS);}while(0);

#define LOG_WARN(FORMAT, ARGS...) LOG(LOG_WARN, FORMAT, ##ARGS)
#define LOG_FATAL(FORMAT, ARGS...) LOG(LOG_FATAL, FORMAT, ##ARGS)
#define LOG_INFO(FORMAT, ARGS...) LOG(LOG_INFO, FORMAT, ##ARGS)
#define LOG_DEBUG(FORMAT, ARGS...) LOG(LOG_DEBUG, FORMAT, ##ARGS)

#define LogD(FORMAT, ARGS...) LOG(LOG_DEBUG, FORMAT, ##ARGS)
#define LogI(FORMAT, ARGS...) LOG(LOG_INFO, FORMAT, ##ARGS)
#define LogF(FORMAT, ARGS...) LOG(LOG_FATAL, FORMAT, ##ARGS)
#define LogW(FORMAT, ARGS...) LOG(LOG_WARN, FORMAT, ##ARGS)
#define LogA(FORMAT, ARGS...) LOG(LOG_FATAL, FORMAT, ##ARGS)
#define LogE(FORMAT, ARGS...) LOG(LOG_ERROR, FORMAT, ##ARGS)


#endif // _I_LOGGER_H